/*
Copyright (c) 2025 HeZongLun
NahidaProject is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/

#pragma once

#ifdef _WIN32
#define ExportSymbol  __declspec(dllexport)
#else
#define ExportSymbol
#endif

#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <ctime>

namespace NahidaProject {
	class ExportSymbol DateTime {
	private:
		int year;
		int month;
		int day;
		int hour;
		int minute;
		int second;

		bool IsLeapYear(int year) const;
		int GetDaysInMonth(int year, int month) const;
		void Validate() const;
		long long ToJulianDay() const;
		void FromJulianDay(long long jd);

	public:
		DateTime() : year(1970), month(1), day(1), hour(0), minute(0), second(0) {

		}

		DateTime(int y, int m, int d, int h = 0, int min = 0, int s = 0) : year(y), month(m), day(d), hour(h), minute(min), second(s) {
			Validate();
		}

		DateTime(const DateTime& other) : year(other.year), month(other.month), day(other.day), hour(other.hour), minute(other.minute), second(other.second) {

		}

		DateTime& operator=(const DateTime& other);
		static DateTime Now();
		static DateTime Parse(const std::string& str, const std::string& format = "%Y-%m-%d %H:%M:%S");
		int GetYear() const;
		int GetMonth() const;
		int GetDay() const;
		int GetHour() const;
		int GetMinute() const;
		int GetSecond() const;

		void SetYear(int y);
		void SetMonth(int m);
		void SetDay(int d);
		void SetHour(int h);
		void SetMinute(int min);
		void SetSecond(int s);
		std::string ToString(const std::string& format = "%Y-%m-%d %H:%M:%S") const;
		double operator-(const DateTime& other) const;
		DateTime operator+(int seconds) const;
		DateTime operator-(int seconds) const;
		DateTime& operator+=(int seconds);
		DateTime& operator-=(int seconds);
		void AddSeconds(int seconds);
		bool operator==(const DateTime& other) const;
		bool operator!=(const DateTime& other) const;
		bool operator<(const DateTime& other) const;
		bool operator<=(const DateTime& other) const;
		bool operator>(const DateTime& other) const;
		bool operator>=(const DateTime& other) const;
		int GetWeekday() const;
		int GetDayOfYear() const;
		bool IsLeapYear() const;
	};
}
